#!/usr/bin/env python3
"""
真实Java后端WVP客户端
Real Java Backend WVP Client

直接连接到Java后端WVP服务，获取真实的设备和通道数据
参考: D:\Projects\MergeTwins30\RuoYi-Wvp-星球版\python-backend\services\wvp_service.py
"""
import asyncio
import aiohttp
import json
import logging
from typing import Dict, List, Any, Optional
from datetime import datetime

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class RealJavaWVPClient:
    """真实Java后端WVP客户端"""
    
    def __init__(self, base_url: str = "http://localhost:8080", username: str = "admin", password: str = "admin123"):
        self.base_url = base_url.rstrip('/')
        self.username = username
        self.password = password
        self.session = None
        self.token = None
        
        # 尝试多个可能的WVP端口
        self.wvp_urls = [
            "http://localhost:18080",  # 默认WVP端口
            "http://localhost:8080",   # 备用端口
            "http://127.0.0.1:18080",
            "http://127.0.0.1:8080",
            "http://localhost:28181",  # GB28181端口
            "http://127.0.0.1:28181"
        ]
    
    async def __aenter__(self):
        """异步上下文管理器入口"""
        self.session = aiohttp.ClientSession(
            timeout=aiohttp.ClientTimeout(total=30),
            headers={
                "Content-Type": "application/json",
                "Accept": "application/json",
                "User-Agent": "Campus-Twin-Python-Backend/1.0"
            }
        )
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """异步上下文管理器出口"""
        if self.session:
            await self.session.close()
    
    async def find_active_wvp_service(self) -> Optional[str]:
        """查找活跃的WVP服务"""
        logger.info("🔍 搜索活跃的Java后端WVP服务...")
        
        for url in self.wvp_urls:
            logger.info(f"  尝试连接: {url}")
            try:
                # 尝试多个可能的API端点
                test_endpoints = [
                    "/api/device/query/devices",
                    "/device/query/devices", 
                    "/api/devices",
                    "/devices",
                    "/wvp/api/device/query/devices"
                ]
                
                for endpoint in test_endpoints:
                    try:
                        test_url = f"{url}{endpoint}?pageNum=1&pageSize=1"
                        logger.debug(f"    测试端点: {test_url}")
                        
                        async with self.session.get(test_url) as response:
                            if response.status == 200:
                                data = await response.json()
                                logger.info(f"  ✅ 找到活跃的WVP服务: {url}{endpoint}")
                                logger.info(f"    响应数据: {json.dumps(data, ensure_ascii=False)[:200]}...")
                                return url, endpoint
                            elif response.status == 401:
                                logger.info(f"  🔐 服务需要认证: {url}{endpoint}")
                                return url, endpoint  # 需要认证但服务存在
                            else:
                                logger.debug(f"    状态码: {response.status}")
                    except Exception as e:
                        logger.debug(f"    端点测试失败: {e}")
                        continue
                        
            except Exception as e:
                logger.debug(f"  连接失败: {e}")
                continue
        
        logger.warning("❌ 未找到活跃的WVP服务")
        return None, None
    
    async def login(self, base_url: str) -> bool:
        """登录获取token"""
        try:
            login_endpoints = [
                "/login",
                "/api/login", 
                "/auth/login",
                "/wvp/login"
            ]
            
            login_data = {
                "username": self.username,
                "password": self.password
            }
            
            for endpoint in login_endpoints:
                try:
                    login_url = f"{base_url}{endpoint}"
                    logger.info(f"尝试登录: {login_url}")
                    
                    async with self.session.post(login_url, json=login_data) as response:
                        if response.status == 200:
                            data = await response.json()
                            if data.get("code") == 200 or data.get("success"):
                                self.token = data.get("token") or data.get("data", {}).get("token")
                                logger.info(f"✅ 登录成功: {login_url}")
                                return True
                            else:
                                logger.warning(f"登录响应异常: {data}")
                        else:
                            logger.debug(f"登录失败，状态码: {response.status}")
                except Exception as e:
                    logger.debug(f"登录端点 {endpoint} 失败: {e}")
                    continue
            
            logger.warning("❌ 所有登录端点都失败")
            return False
            
        except Exception as e:
            logger.error(f"登录异常: {e}")
            return False
    
    def _get_headers(self) -> Dict[str, str]:
        """获取请求头"""
        headers = {
            "Content-Type": "application/json",
            "Accept": "application/json"
        }
        if self.token:
            headers["Authorization"] = f"Bearer {self.token}"
        return headers
    
    async def get_devices_from_java(self, base_url: str, api_endpoint: str) -> List[Dict[str, Any]]:
        """从Java后端获取设备列表"""
        try:
            # 尝试不同的设备查询端点
            device_endpoints = [
                f"{api_endpoint}?pageNum=1&pageSize=1000",
                f"{api_endpoint}",
                "/api/device/query/devices?pageNum=1&pageSize=1000",
                "/device/query/devices?pageNum=1&pageSize=1000"
            ]
            
            headers = self._get_headers()
            
            for endpoint in device_endpoints:
                try:
                    url = f"{base_url}{endpoint}"
                    logger.info(f"获取设备列表: {url}")
                    
                    async with self.session.get(url, headers=headers) as response:
                        if response.status == 200:
                            data = await response.json()
                            logger.info(f"设备API响应: {json.dumps(data, ensure_ascii=False)[:300]}...")
                            
                            # 尝试不同的数据结构
                            devices = []
                            if isinstance(data, list):
                                devices = data
                            elif isinstance(data, dict):
                                devices = (data.get("rows") or 
                                         data.get("data") or 
                                         data.get("list") or 
                                         data.get("devices") or [])
                            
                            if devices:
                                logger.info(f"✅ 从Java后端获取到 {len(devices)} 个设备")
                                return devices
                            else:
                                logger.warning(f"设备列表为空: {data}")
                        
                        elif response.status == 401:
                            logger.warning("需要重新认证")
                            if await self.login(base_url):
                                headers = self._get_headers()
                                continue
                        else:
                            logger.warning(f"获取设备失败，状态码: {response.status}")
                            
                except Exception as e:
                    logger.debug(f"设备端点 {endpoint} 失败: {e}")
                    continue
            
            logger.warning("❌ 所有设备端点都失败")
            return []
            
        except Exception as e:
            logger.error(f"获取设备列表异常: {e}")
            return []
    
    async def get_device_channels_from_java(self, base_url: str, device_id: str) -> List[Dict[str, Any]]:
        """从Java后端获取设备通道"""
        try:
            # 尝试不同的通道查询端点
            channel_endpoints = [
                f"/api/device/query/devices/{device_id}/channels?pageNum=1&pageSize=1000",
                f"/device/query/devices/{device_id}/channels?pageNum=1&pageSize=1000",
                f"/api/device/{device_id}/channels",
                f"/device/{device_id}/channels",
                f"/api/channels?deviceId={device_id}",
                f"/channels?deviceId={device_id}"
            ]
            
            headers = self._get_headers()
            
            for endpoint in channel_endpoints:
                try:
                    url = f"{base_url}{endpoint}"
                    logger.debug(f"获取设备 {device_id} 通道: {url}")
                    
                    async with self.session.get(url, headers=headers) as response:
                        if response.status == 200:
                            data = await response.json()
                            logger.debug(f"通道API响应: {json.dumps(data, ensure_ascii=False)[:200]}...")
                            
                            # 尝试不同的数据结构
                            channels = []
                            if isinstance(data, list):
                                channels = data
                            elif isinstance(data, dict):
                                channels = (data.get("rows") or 
                                          data.get("data") or 
                                          data.get("list") or 
                                          data.get("channels") or [])
                            
                            logger.info(f"设备 {device_id} 有 {len(channels)} 个通道")
                            return channels
                            
                        elif response.status == 401:
                            logger.warning("需要重新认证")
                            if await self.login(base_url):
                                headers = self._get_headers()
                                continue
                        else:
                            logger.debug(f"获取通道失败，状态码: {response.status}")
                            
                except Exception as e:
                    logger.debug(f"通道端点 {endpoint} 失败: {e}")
                    continue
            
            logger.debug(f"设备 {device_id} 没有找到通道")
            return []
            
        except Exception as e:
            logger.error(f"获取设备 {device_id} 通道异常: {e}")
            return []
    
    async def sync_real_wvp_data(self) -> Dict[str, Any]:
        """同步真实WVP数据"""
        try:
            logger.info("🚀 开始从Java后端同步真实WVP数据...")
            
            # 1. 查找活跃的WVP服务
            service_info = await self.find_active_wvp_service()
            if not service_info or not service_info[0]:
                return {
                    "success": False,
                    "error": "未找到活跃的Java后端WVP服务",
                    "devices": [],
                    "channels": {}
                }
            
            base_url, api_endpoint = service_info
            logger.info(f"使用WVP服务: {base_url}")
            
            # 2. 尝试登录（如果需要）
            await self.login(base_url)
            
            # 3. 获取设备列表
            devices = await self.get_devices_from_java(base_url, api_endpoint)
            
            if not devices:
                return {
                    "success": False,
                    "error": "Java后端WVP服务没有返回设备数据",
                    "devices": [],
                    "channels": {}
                }
            
            logger.info(f"📊 从Java后端获取到 {len(devices)} 个真实WVP设备")
            
            # 4. 获取每个设备的通道
            channels_map = {}
            total_channels = 0
            
            for device in devices:
                device_id = (device.get("deviceId") or 
                           device.get("id") or 
                           device.get("device_id"))
                
                if device_id:
                    device_channels = await self.get_device_channels_from_java(base_url, device_id)
                    channels_map[device_id] = device_channels
                    total_channels += len(device_channels)
                    
                    device_name = (device.get("name") or 
                                 device.get("deviceName") or 
                                 device.get("device_name") or 
                                 device_id)
                    
                    logger.info(f"  设备: {device_id} ({device_name}) - {len(device_channels)} 个通道")
            
            logger.info(f"📈 总计获取到 {total_channels} 个通道")
            
            return {
                "success": True,
                "wvp_url": base_url,
                "api_endpoint": api_endpoint,
                "devices": devices,
                "channels": channels_map,
                "total_devices": len(devices),
                "total_channels": total_channels,
                "message": f"成功从Java后端获取 {len(devices)} 个设备和 {total_channels} 个通道"
            }
            
        except Exception as e:
            logger.error(f"同步真实WVP数据失败: {e}", exc_info=True)
            return {
                "success": False,
                "error": str(e),
                "devices": [],
                "channels": {}
            }


async def test_real_java_connection():
    """测试真实Java后端连接"""
    try:
        logger.info("🧪 测试真实Java后端WVP连接...")
        
        async with RealJavaWVPClient() as client:
            result = await client.sync_real_wvp_data()
            
            if result["success"]:
                logger.info("✅ 连接成功!")
                logger.info(f"  WVP服务地址: {result['wvp_url']}")
                logger.info(f"  API端点: {result['api_endpoint']}")
                logger.info(f"  设备数量: {result['total_devices']}")
                logger.info(f"  通道数量: {result['total_channels']}")
                
                # 显示设备详情
                if result["devices"]:
                    logger.info("📋 设备详情:")
                    for i, device in enumerate(result["devices"][:3]):  # 只显示前3个
                        device_id = (device.get("deviceId") or 
                                   device.get("id") or 
                                   device.get("device_id"))
                        device_name = (device.get("name") or 
                                     device.get("deviceName") or 
                                     device.get("device_name") or 
                                     device_id)
                        
                        logger.info(f"  {i+1}. {device_id} - {device_name}")
                        logger.info(f"     制造商: {device.get('manufacturer', 'N/A')}")
                        logger.info(f"     型号: {device.get('model', 'N/A')}")
                        logger.info(f"     IP: {device.get('ip') or device.get('hostAddress', 'N/A')}")
                        logger.info(f"     状态: {'在线' if device.get('online') else '离线'}")
                        
                        # 显示通道
                        channels = result["channels"].get(device_id, [])
                        if channels:
                            logger.info(f"     通道数: {len(channels)}")
                            for j, channel in enumerate(channels[:2]):  # 只显示前2个通道
                                channel_id = (channel.get("channelId") or 
                                            channel.get("id") or 
                                            channel.get("channel_id"))
                                channel_name = (channel.get("name") or 
                                              channel.get("channelName") or 
                                              channel.get("channel_name") or 
                                              channel_id)
                                logger.info(f"       - {channel_id}: {channel_name}")
                        else:
                            logger.info(f"     通道数: 0")
                
                return result
            else:
                logger.error(f"❌ 连接失败: {result['error']}")
                return None
                
    except Exception as e:
        logger.error(f"测试连接异常: {e}")
        return None


async def sync_real_data_to_database():
    """将真实数据同步到数据库"""
    try:
        from database.simple_db import get_database_manager
        from api.services import CameraService
        
        logger.info("💾 开始将真实WVP数据同步到数据库...")
        
        # 1. 获取真实数据
        async with RealJavaWVPClient() as client:
            result = await client.sync_real_wvp_data()
            
            if not result["success"]:
                logger.error(f"获取真实数据失败: {result['error']}")
                return False
        
        # 2. 同步到数据库
        db = get_database_manager()
        camera_service = CameraService()
        
        # 清空现有WVP数据
        logger.info("🗑️ 清空现有WVP数据...")
        db.execute_update("DELETE FROM wvp_devices", ())
        db.execute_update("DELETE FROM wvp_channels", ())
        
        devices = result["devices"]
        channels_map = result["channels"]
        
        synced_devices = 0
        synced_channels = 0
        converted_cameras = 0
        
        # 3. 同步设备
        logger.info("📥 同步设备到数据库...")
        for device in devices:
            device_id = (device.get("deviceId") or 
                       device.get("id") or 
                       device.get("device_id"))
            
            if not device_id:
                continue
            
            device_name = (device.get("name") or 
                         device.get("deviceName") or 
                         device.get("device_name") or 
                         f"设备-{device_id}")
            
            # 插入设备
            device_query = """
                INSERT INTO wvp_devices (
                    device_id, device_name, manufacturer, model, ip, port,
                    status, register_time, keepalive_time, created_at
                ) VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
            """
            
            device_params = (
                device_id,
                device_name,
                device.get("manufacturer", ""),
                device.get("model", ""),
                device.get("ip") or device.get("hostAddress", ""),
                device.get("port", 5060),
                "online" if device.get("online") else "offline"
            )
            
            db.execute_insert(device_query, device_params)
            synced_devices += 1
            logger.info(f"  ✅ 同步设备: {device_id} ({device_name})")
            
            # 4. 同步通道
            channels = channels_map.get(device_id, [])
            
            if not channels:
                # 如果没有通道，创建默认通道
                channels = [{
                    "channelId": device_id,
                    "name": f"{device_name}-默认通道",
                    "status": "ON" if device.get("online") else "OFF",
                    "address": f"{device_name}位置",
                    "longitude": 0.0,
                    "latitude": 0.0
                }]
            
            for channel in channels:
                channel_id = (channel.get("channelId") or 
                            channel.get("id") or 
                            channel.get("channel_id") or 
                            device_id)
                
                channel_name = (channel.get("name") or 
                              channel.get("channelName") or 
                              channel.get("channel_name") or 
                              f"通道-{channel_id}")
                
                # 插入通道
                channel_query = """
                    INSERT INTO wvp_channels (
                        device_id, channel_id, channel_name, status, 
                        longitude, latitude, address, created_at
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
                """
                
                channel_params = (
                    device_id,
                    channel_id,
                    channel_name,
                    "online" if channel.get("status") == "ON" else "offline",
                    channel.get("longitude", 0.0),
                    channel.get("latitude", 0.0),
                    channel.get("address", f"{device_name}位置")
                )
                
                db.execute_insert(channel_query, channel_params)
                synced_channels += 1
                logger.info(f"    ✅ 同步通道: {channel_id} ({channel_name})")
                
                # 5. 转换为摄像头
                # 检查是否已经有对应的摄像头
                existing_camera = db.get_camera_by_wvp_device(device_id, channel_id)
                if existing_camera:
                    logger.info(f"      摄像头已存在: {existing_camera['name']}")
                    continue
                
                # 生成唯一的摄像头名称
                base_name = f"{device_name}-{channel_name}"
                unique_name = base_name
                counter = 1
                
                while db.get_camera_by_name(unique_name):
                    unique_name = f"{base_name}_{counter}"
                    counter += 1
                
                # 创建摄像头
                camera_data = {
                    'name': unique_name,
                    'wvp_device_id': device_id,
                    'wvp_channel_id': channel_id,
                    'location': channel.get('address', f"{device_name}位置"),
                    'longitude': float(channel.get('longitude', 0.0)),
                    'latitude': float(channel.get('latitude', 0.0)),
                    'description': f"从Java后端WVP设备 {device_name}({device_id}) 通道 {channel_id} 转换",
                    'ai_enabled': True,
                    'status': 'online' if channel.get('status') == 'online' else 'offline',
                    'rtsp_url': f"rtsp://{device.get('ip', '192.168.1.100')}:554/h264/ch{channel_id}/main/av_stream"
                }
                
                try:
                    camera_id = await camera_service.create_camera(camera_data)
                    if camera_id:
                        converted_cameras += 1
                        logger.info(f"      🎥 转换为摄像头: {camera_id} ({unique_name})")
                    else:
                        logger.error(f"      ❌ 摄像头转换失败: 未返回ID")
                except Exception as e:
                    logger.error(f"      ❌ 摄像头转换失败: {e}")
        
        logger.info("🎉 真实WVP数据同步完成!")
        logger.info(f"  同步设备: {synced_devices}")
        logger.info(f"  同步通道: {synced_channels}")
        logger.info(f"  转换摄像头: {converted_cameras}")
        
        return True
        
    except Exception as e:
        logger.error(f"同步真实数据到数据库失败: {e}", exc_info=True)
        return False


if __name__ == "__main__":
    print("🔌 真实Java后端WVP客户端")
    print("=" * 50)
    print("此工具将:")
    print("1. 搜索并连接到真实的Java后端WVP服务")
    print("2. 获取真实的WVP设备和通道数据")
    print("3. 将数据同步到Python后端数据库")
    print("4. 转换为摄像头数据")
    print("=" * 50)
    
    choice = input("\n选择操作 (1: 测试连接, 2: 同步数据, 3: 退出): ")
    
    if choice == "1":
        print("\n🧪 测试Java后端WVP连接...")
        result = asyncio.run(test_real_java_connection())
        
        if result:
            print(f"\n✅ 连接测试成功!")
            print(f"找到 {result['total_devices']} 个设备和 {result['total_channels']} 个通道")
        else:
            print("\n❌ 连接测试失败!")
    
    elif choice == "2":
        print("\n💾 开始同步真实WVP数据...")
        success = asyncio.run(sync_real_data_to_database())
        
        if success:
            print("\n🎉 同步成功!")
        else:
            print("\n❌ 同步失败!")
    
    else:
        print("👋 退出")